﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Main.Common;

namespace Main.UI.Components
{
    public class FileMenuItemList : IEnumerable<IFileMenuItem>
    {
        private class Sorter 
        {
            private static Type All = typeof(FileMenuItems.MenuItemConstants.All);
            private static Type Any = typeof(FileMenuItems.MenuItemConstants.Any);
            private static Type None = typeof(FileMenuItems.MenuItemConstants.None);

            public enum Direction
            {
                SWAP,
                KEEP,
            }
            public Direction Compare(IFileMenuItem bottom, IFileMenuItem top)
            {
                if (bottom == null && top == null) return Direction.KEEP;
                if (bottom == null) return Direction.SWAP;
                if (top == null) return Direction.SWAP;
           
                #region X should be displayed before Y
                if (bottom.ShouldBeDisplayedAbove != null && bottom.ShouldBeDisplayedAbove.Equals(top))
                    return Direction.SWAP;
                #endregion

                #region Y should be displayed before X
                if (top.ShouldBeDisplayedAbove != null && top.ShouldBeDisplayedAbove.Equals(bottom))
                    return Direction.KEEP;
                #endregion

                #region X should be displayed after Y
                if (bottom.ShouldBeDisplayedBelow != null && bottom.ShouldBeDisplayedBelow.Equals(top))
                    return Direction.KEEP;
                #endregion

                #region Y should be displayed after X
                if (top.ShouldBeDisplayedBelow != null && top.ShouldBeDisplayedBelow.Equals(bottom))
                    return Direction.SWAP;
                #endregion

                #region X should be displayed before EVERYTHING / ALL
                if (bottom.ShouldBeDisplayedAbove != null && bottom.ShouldBeDisplayedAbove.Equals(All))
                    return Direction.SWAP;
                #endregion

                #region X should be displayed before NOTHING (ie all should be displayed before X) or X should be at the end
                if (bottom.ShouldBeDisplayedAbove != null && bottom.ShouldBeDisplayedAbove.Equals(None))
                    return Direction.KEEP;
                #endregion

                #region Y should be displayed before EVERYTHING / ALL
                if (top.ShouldBeDisplayedAbove != null && top.ShouldBeDisplayedAbove.Equals(All))
                    return Direction.KEEP;
                #endregion

                #region Y should be displayed before NOTHING (ie all should be displayed before Y) or Y should be at the end
                if (top.ShouldBeDisplayedAbove != null && top.ShouldBeDisplayedAbove.Equals(None))
                    return Direction.SWAP;
                #endregion

                #region X should be displayed after EVERYTHING / ALL
                if (bottom.ShouldBeDisplayedBelow != null && bottom.ShouldBeDisplayedBelow.Equals(All))
                    return Direction.KEEP;
                #endregion

                #region X should be displayed after NOTHING (ie all should be displayed after X) or X should be at the top
                if (bottom.ShouldBeDisplayedBelow != null && bottom.ShouldBeDisplayedBelow.Equals(None))
                    return Direction.SWAP;
                #endregion

                #region Y should be displayed after EVERYTHING / ALL
                if (top.ShouldBeDisplayedBelow != null && top.ShouldBeDisplayedBelow.Equals(All))
                    return Direction.SWAP;
                #endregion

                #region Y should be displayed after NOTHING (ie all should be displayed after Y) or Y should be at the top
                if (top.ShouldBeDisplayedBelow != null && top.ShouldBeDisplayedBelow.Equals(None))
                    return Direction.KEEP;
                #endregion

                return Direction.KEEP;
            }
        }

        private List<IFileMenuItem> MENU_ITEMS = null;
        
        public FileMenuItemList()
        { Init(); }

        private void Init()
        {
            MENU_ITEMS = new List<IFileMenuItem>(AppDomain.CurrentDomain.FindAll<IFileMenuItem>());
            Sort(MENU_ITEMS);
        }

        private void Sort(List<IFileMenuItem> list)
        {
            Sorter logic = new Sorter();
            bool changed;
            do
            {
                changed = false;
                for (int index = (list.Count - 1); index > 0; index--)
                {
                    IFileMenuItem bottom = list[index];
                    IFileMenuItem top = list[index-1];
                    if (logic.Compare(bottom, top) == Sorter.Direction.SWAP)
                    {
                        list[index] = top;
                        list[index - 1] = bottom;
                        changed = true;
                    }
                }
            } while (changed);
        }
    
        public IEnumerator<IFileMenuItem> GetEnumerator()
        {
            return MENU_ITEMS.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return MENU_ITEMS.GetEnumerator();
        }
    }
}
